import java.awt.*;
import java.net.URL;

import com.sun.j3d.utils.timer.J3DTimer;


public abstract class Core {
	private static final int NO_DELAYS_PER_YIELD = 16;
	  /* Number of frames with a delay of 0 ms before the animation thread yields
	     to other running threads. */
	private static int MAX_FRAME_SKIPS = 5;
    // no. of frames that can be skipped in any one animation loop
    // i.e the games state is updated but not rendered
	
	private static final DisplayMode[] MODES = {
		new DisplayMode(1280, 1084, 32, 0),
		new DisplayMode(800,600,32,0),
		new DisplayMode(800,600,24,0),
		new DisplayMode(800,600,16,0),
		new DisplayMode(640,480,32,0),
		new DisplayMode(640,480,24,0),
		new DisplayMode(640,480,16,0),
	};
	private boolean running;
	protected ScreenManager s;
	
	//stop method
	public void stop(){
		running = false;
	}
	
	//call init and gameloop
	public void run(){
		try{
			init();
			gameLoop();
		}finally{
			s.restoreScreen();
		}
	}
	
	//set to full screen
	public void init(){
		s = new ScreenManager();
		DisplayMode dm = s.findFirstCompatibleMode(MODES);
		s.setFullScreen(dm);
		
		Window w = s.getFullScreenWindow();
		w.setFont(new Font("Arial", Font.PLAIN, 20));
		w.setBackground(Color.BLACK);
		w.setForeground(Color.WHITE);
		running = true;
	}
	
	//main game loop
	public void gameLoop(){
		/// SLEEP VARS ///////
		long startTime = System.currentTimeMillis();
		long cumTime = startTime;
		long beforeTime, afterTime, timeDiff, sleepTime;
	    long overSleepTime = 0L;
	    int noDelays = 0;
	    long excess = 0L;
	    beforeTime = J3DTimer.getValue();
	    long period = 20;
	    /////////////////////////////
	    
	    
	    
		while(running){
			long timePassed = System.currentTimeMillis() - cumTime;
			cumTime += timePassed;
			
			update(timePassed);
			
			Graphics2D g = s.getGraphics();
			draw(g);
			g.dispose();
			s.update();
			
			////// SLEEPING CODE ///////
				

			

		      afterTime = J3DTimer.getValue();
		      timeDiff = afterTime - beforeTime;
		      sleepTime = (period - timeDiff) - overSleepTime;  

		      if (sleepTime > 0) {   // some time left in this cycle
		        try {
		          Thread.sleep(sleepTime/1000000L);  // nano -> ms
		        }catch(InterruptedException ex){}
		        overSleepTime = (J3DTimer.getValue() - afterTime) - sleepTime;
		      } else {    // sleepTime <= 0; the frame took longer than the period
		        excess -= sleepTime;  // store excess time value
		        overSleepTime = 0L;

		        if (++noDelays >= NO_DELAYS_PER_YIELD) {
		          Thread.yield();   // give another thread a chance to run
		          noDelays = 0;
		        }
			}
		      beforeTime = J3DTimer.getValue();	      
		}
	}
	
	// finds folder of the project
	protected static String currDirectory() {
		final URL location;
		final String classLocation = Game.class.getName().replace('.', '/')
				+ ".class";
		final ClassLoader loader = Game.class.getClassLoader();
		if (loader == null) {
			return ("Cannot load the class");
		} else {
			location = loader.getResource(classLocation);
			String directory = location.toString().substring(6,
					location.toString().length() - 14);
			directory = directory.replace("%20", " ");
			directory = directory.replace("/", "\\");
			return (directory);
		}
	}
	
	//update animation
	public void update(long timePassed){}
	
	//draws to screen
	public abstract void draw(Graphics2D g);
}
